use std::{
	fmt::{self, Debug},
	io,
	net::AddrParseError,
	num::ParseIntError,
};

use bytes::Bytes;
use tokio::sync::{
	broadcast,
	mpsc::{self, error::TrySendError},
};

pub enum Error {
	OtherError(String),
	///一般占位用
	InternalError,
	AuthFailed,
	///数据库读写异常
	SqlxError(sqlx::Error),
	///内部数据交换异常
	DataExchangeError(String),
	///未实现异常
	NoImplementError(&'static str),
	///节点替换.此类型并非一个异常.做为节点替换的标志
	ReplaceNode,
	///转码异常
	CodeParseError(String),
	///消息队列异常
	QueueMsgError(String),
	///通用异常
	UniversalError(&'static str),
	///没有可用的通道
	NoAvailableChannel,
	///设备操作失败
	DeviceOperatorError(u32, String),
	///IO错误,包括网络和文件等
	IOError(String),
	///代码逻辑错误,指代码执行过程异常
	LogicalError(&'static str),
	UserNotRegister, //用户未注册
	///无效的数据
	InvalidData(&'static str),
	///未找到需要的信息
	NotFound(&'static str),
	SipErrorRecover(Bytes),
	MediaError(&'static str),
}

///错误标记,用于context方法返回指定的错误
pub enum ErrMark {
	UnknowErrorMark,
	InternalErrorMark,
	AuthFailedMark,
}

impl std::error::Error for Error {}

//实现Display
impl std::fmt::Display for Error {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		self.fmt(f)
	}
}

//实现Display
impl std::fmt::Debug for Error {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		self.fmt(f)
	}
}

impl Error {
	#[inline]
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		match self {
			Error::OtherError(source) => write!(f, "OtherError..其他异常.来源:{}", source),
			Error::IOError(source) => write!(f, "IOError..IO异常.来源:{}", source),
			Error::InternalError => write!(f, "InternalError..内部错误,一般占位用.."),
			Error::AuthFailed => write!(f, "AuthFailed..校验失败."),
			Error::SqlxError(source) => write!(f, "SqlxError..数据库操作异常,源:{}", source),
			Error::DataExchangeError(source) => {
				write!(f, "DataExchangeError..内部数据交换异常.来源:{}", source)
			}
			Error::NoImplementError(e) => write!(f, "NoImplementType..未实现的:{}", e),
			Error::ReplaceNode => write!(f, "ReplaceNode..替换处理节点"),
			Error::CodeParseError(e) => write!(f, "CodeParseError..转码出现异常:{}", e),
			Error::QueueMsgError(source) => write!(f, "QueueMsgError..消息队列出现异常:{}", source),
			Error::UniversalError(e) => write!(f, "UniversalError..通用错误,{e}"),
			Error::NoAvailableChannel => write!(f, "NoAvailableChannel..没有可用的通道.."),
			Error::DeviceOperatorError(ch_id, e) => {
				write!(f, "OperatorError..设备操作失败,id:{} : {}", ch_id, e)
			}
			Error::LogicalError(e) => write!(f, "LogicalError..逻辑错误,{e}"),
			Error::InvalidData(e) => write!(f, "InvalidData无效的数据,{e}"),
			Error::NotFound(e) => write!(f, "{e}"),
			Error::SipErrorRecover(_) => write!(f, "Sip回复一个异常"),
			Error::UserNotRegister => write!(f, "用户未注册"),
			Error::MediaError(e) => write!(f, "{e}"),
		}
	}

	fn into_error<E>(error: E, mark: ErrMark) -> Error
	where
		E: std::error::Error + 'static,
	{
		match mark {
			ErrMark::UnknowErrorMark => Error::OtherError(error.to_string()),
			ErrMark::InternalErrorMark => Error::InternalError,
			ErrMark::AuthFailedMark => Error::AuthFailed,
		}
	}
}

impl Error {
	pub fn new() -> Self {
		Error::OtherError(String::default())
	}
}

pub trait ResultContext<T, E>: Sized {
	fn context(self, context: ErrMark) -> Result<T, Error>;
	fn context_with(self, err: Error) -> Result<T, Error>;
}

impl<T, E: std::error::Error + 'static> ResultContext<T, E> for Result<T, E> {
	fn context(self, mark: ErrMark) -> Result<T, Error> {
		match self {
			Ok(v) => Ok(v),
			Err(e) => Err(Error::into_error(e, mark)),
		}
	}

	fn context_with(self, err: Error) -> Result<T, Error> {
		match self {
			Ok(v) => Ok(v),
			Err(_) => Err(err),
		}
	}
}

impl From<sqlx::Error> for Error {
	fn from(error: sqlx::Error) -> Self {
		Self::SqlxError(error)
	}
}

impl<T> From<mpsc::error::SendError<T>> for Error
where
	T: Debug + 'static,
{
	fn from(value: mpsc::error::SendError<T>) -> Self {
		Self::DataExchangeError(value.to_string())
	}
}

impl<T> From<broadcast::error::SendError<T>> for Error
where
	T: Debug + 'static,
{
	fn from(value: broadcast::error::SendError<T>) -> Self {
		Self::DataExchangeError(value.to_string())
	}
}

impl From<io::Error> for Error {
	fn from(value: io::Error) -> Self {
		Self::IOError(value.to_string())
	}
}

impl From<AddrParseError> for Error {
	fn from(value: AddrParseError) -> Self {
		Self::IOError(value.to_string())
	}
}

impl From<ParseIntError> for Error {
	fn from(value: ParseIntError) -> Self {
		Self::CodeParseError(value.to_string())
	}
}

impl<T> From<TrySendError<T>> for Error {
	fn from(value: TrySendError<T>) -> Self {
		Self::IOError(format!("{value:?}"))
	}
}
impl From<&'static str> for Error {
	fn from(value: &'static str) -> Self {
		Error::LogicalError(value)
	}
}
